﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.Reflection;
using System.Media;
using System.IO;
namespace Gobang
{
    public partial class Form1 : Form
    {
        private Client clientProxy;
        private bool bGameStart = false;
        private Piece pLastPiece = null;
        public string roomID = "";
        
        public Form1(Client c)
        {
            InitializeComponent();
            clientProxy = c;
            clientProxy.m_requestHandler = HandleMsg;
        }
        public Form1()
        {
            InitializeComponent();
            clientProxy = new Client();
            clientProxy.m_requestHandler += HandleMsg;
            bool res = clientProxy.Connect("127.0.0.1", 1009);
            //bool res = clientProxy.Connect("47.103.69.4", 1009);
            if (!res)
            {
                Debug.WriteLine("Connect Server failed");
                labelInfo.Text = "连接服务器失败";
            }
        }
        private void HandleMsg(object[] args)
        {
            List<object> Args = new List<object>(args);
            if (args[0].GetType() != typeof(string))
            {
                Debug.WriteLine("first argument should be string");
                return;
            }
            string funcname = args[0] as string;
            Args.RemoveAt(0);
            MethodInfo minfo = this.GetType().GetMethod(funcname);
            if (minfo!=null)
            {
                try
                {
                    minfo.Invoke(this, Args.ToArray());
                    Debug.WriteLine("ClientTool::" + funcname + " executed.");
                }
                catch (TargetParameterCountException e)
                {
                    Debug.WriteLine("ClientTool::" + funcname + " execute error: " + e.Message);
                }
                catch (TargetInvocationException e)
                {
                    Debug.WriteLine("ClientTool::" + funcname + " execute error: " + e.Message);
                }
            }
            else
            {
                Debug.WriteLine("ClientTool::" + funcname + " not found.");
            }
        }
        public void Create_Piece(int row, int col, int isWhite)
        {
            //string soundFileName = "Gobang.res.knock.wav";
            //using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(soundFileName))
            //{
            //    SoundPlayer player = new SoundPlayer(stream);
            //    if (player != null)
            //    {
            //        player.Play();
            //    }
            //    else
            //    {
            //        Debug.WriteLine("unable to load audio resource.");
            //    }
            //}
            if (pLastPiece != null)
            {
                if (pLastPiece.GetType() == typeof(WhitePiece))
                {
                    pLastPiece.Image = Properties.Resources.white;
                }
                else
                {
                    pLastPiece.Image = Properties.Resources.black;
                }
            }
            Piece p;
            if (isWhite == 1)
            {
                p = new WhitePiece(row, col);
                p.Image = Properties.Resources.whiteR;
            }
            else
            {
                p = new BlackPiece(row, col);
                p.Image = Properties.Resources.blackR;
            }
            
            pLastPiece = p;
            this.Controls.Add(p);
            p.Parent = picBoard;
        }
        public void Delete_AllPiece()
        {
            List<Control> L = new List<Control>();
            foreach (Control p in picBoard.Controls)
            {
                Type t = p.GetType();
                if (t == typeof(WhitePiece) || t == typeof(BlackPiece))
                {
                    L.Add(p);
                }
            }
            foreach (Control p in L)
            {
                picBoard.Controls.Remove(p);
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            labelInfo.Text = "请准备";
            //bool res = clientProxy.Connect("127.0.0.1", 1009);
            //bool res = clientProxy.Connect("47.103.69.4", 1009);
            //if (!res)
            //{
            //    Debug.WriteLine("Connect Server failed");
            //    labelInfo.Text = "连接服务器失败";
            //}
            this.Text = "五子棋" + "（房间号：" + roomID + "）";
            Size pSize = picBoard.Size;
            int L = Math.Min(pSize.Height, pSize.Width);
            int GL = (int)(L * StaticData.RATIO / 14);
            StaticData.GRID_X = GL;
            StaticData.GRID_Y = GL;
            StaticData.SNIP_R = GL / 3;
            StaticData.OFFSET_Y = (int)(0.07 * L);
            StaticData.OFFSET_X = (int)(0.076 * L);
            Piece.PIECE_R = GL * 4 / 5;
            int Diff = pSize.Height - pSize.Width;
            if (pSize.Height > pSize.Width)
            {
                StaticData.OFFSET_Y += Diff / 2;
            }
            else
            {
                StaticData.OFFSET_X -= Diff / 2;
            }
        }
        private Point GetNearestPoint(int vx, int vy)
        {
            int x = vx - StaticData.OFFSET_X;
            int y = vy - StaticData.OFFSET_Y;
            int nx = (int)Math.Round((double)x / StaticData.GRID_X);
            int ny = (int)Math.Round((double)y / StaticData.GRID_Y);
            return new Point(nx, ny);
        }
        private void picBoard_MouseMove(object sender, MouseEventArgs e)
        {
            Point p = GetNearestPoint(e.X, e.Y);
            int dx = e.X - StaticData.OFFSET_X - p.X * StaticData.GRID_X;
            int dy = e.Y - StaticData.OFFSET_Y - p.Y * StaticData.GRID_Y;
            if (Math.Abs(dx) < StaticData.SNIP_R && Math.Abs(dy) < StaticData.SNIP_R)
            {
                this.Cursor = Cursors.Hand;
            }
            else
            {
                this.Cursor = Cursors.Arrow;
            }
        }

        private void picBoard_Click(object sender, EventArgs E)
        {
            MouseEventArgs e = (MouseEventArgs)E;
            Point p = GetNearestPoint(e.X, e.Y);
            int dx = e.X - StaticData.OFFSET_X - p.X * StaticData.GRID_X;
            int dy = e.Y - StaticData.OFFSET_Y - p.Y * StaticData.GRID_Y;
            if (Math.Abs(dx) < StaticData.SNIP_R && Math.Abs(dy) < StaticData.SNIP_R)
            {
                clientProxy.SendParams("PieceOn", p.X, p.Y);
            }
        }

        public void ShowWinLose(int bWin)
        {
            if (bWin == 1)
            {
                picResult.Image = Properties.Resources.win;
            }
            else
            {
                picResult.Image = Properties.Resources.lose;
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            clientProxy.m_client.Tick();
        }
        public void Player_Disconnect()
        {
            labelInfo.Text = "玩家已断开连接";
        }
        public void Receive_MyTurn(int leftTime)
        {
            progressBarOther.Visible = false;
            progressBarMine.Visible = true;
            labelInfo.Text = string.Format("你的回合，剩余时间：{0} 秒", leftTime);
            progressBarMine.Value = leftTime;
        }
        public void Receive_OtherTurn(int leftTime)
        {
            progressBarMine.Visible = false;
            progressBarOther.Visible = true;
            labelInfo.Text = string.Format("对方回合，剩余时间：{0} 秒", leftTime);
            progressBarOther.Value = leftTime;
        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (clientProxy.m_client.IsConnected())
            {
                clientProxy.SendParams("QuitGame");     //退出游戏
            }
        }
        
        
        public void GAME_START()
        {
            Delete_AllPiece();
            labelInfo.Text = "游戏开始";
            picResult.Image = null;
            bGameStart = true;
        }
        public void GAME_OVER()
        {
            labelInfo.Text = "游戏结束";
            bGameStart = false;
        }
        public void PIECE_COLOR(int isWhite)
        {
            if (isWhite == 0)
            {
                picPieceBoxMine.Image = Properties.Resources.blackBox;
                picPieceBoxOther.Image = Properties.Resources.whiteBox;
            }
            else
            {
                picPieceBoxMine.Image = Properties.Resources.whiteBox;
                picPieceBoxOther.Image = Properties.Resources.blackBox;
            }
        }


        public void Give_Up()
        {
            labelInfo.Text = "对手认输";
        }

        private void btnGiveup_Click(object sender, EventArgs e)
        {
            if (bGameStart)
            {
                clientProxy.SendParams("GiveUp");
            }
        }
        public void TakeBackRequest()
        {
            DialogResult res = MessageBox.Show("对方请求悔棋", "悔棋", MessageBoxButtons.YesNo);
            if (res == DialogResult.Yes)
            {
                clientProxy.SendParams("TakeBackResponse", 1);
            }
            else
            {
                clientProxy.SendParams("TakeBackResponse", 0);
            }
        }
        public void Agree_TackBack()
        {
            labelInfo.Text = "对方同意悔棋";
        }
        public void Disagree_TackBack()
        {
            labelInfo.Text = "对方不同意悔棋";
        }
        public void Delete_Piece(int i, int j)
        {
            foreach (Control p in picBoard.Controls)
            {
                Type t = p.GetType();
                if (t == typeof(WhitePiece) || t == typeof(BlackPiece))
                {
                    Piece pbase = p as Piece;
                    if (pbase.i == i && pbase.j == j)
                    {
                        picBoard.Controls.Remove(p);
                        break;
                    }
                }
            }
        }

        private void btnTakeBack_Click(object sender, EventArgs e)
        {
            if (bGameStart)
            {
                clientProxy.SendParams("TakeBack");
            }
        }
        public void Mark_Last_Piece(int i, int j)
        {
            foreach (Control p in picBoard.Controls)
            {
                Type t = p.GetType();
                if (t == typeof(WhitePiece) || t == typeof(BlackPiece))
                {
                    Piece pbase = p as Piece;
                    if (pbase.i == i && pbase.j == j)
                    {
                        pLastPiece = pbase;
                        if (t == typeof(WhitePiece))
                        {
                            pLastPiece.Image = Properties.Resources.whiteR;
                        }
                        else
                        {
                            pLastPiece.Image = Properties.Resources.blackR;
                        }
                        break;
                    }
                }
            }
        }

        private void btnPrepare_Click(object sender, EventArgs e)
        {
            if (!bGameStart)
            {
                clientProxy.SendParams("READY", 1);
            }
        }
        public void OTHER_PREPARE(int state)
        {
            if (state == 0)
            {
                labelInfo.Text = "对方未准备";
            }
            else
            {
                labelInfo.Text = "对方已准备";
            }
        }
    }
}
